using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Banshee.Base.Gui.Dialogs
{
    using Banshee.Base;
    using Banshee.Widgets;
    using Banshee.Configuration.Schema;
    using Banshee.Winforms;
    public partial class TrackEditor : ComponentFactory.Krypton.Toolkit.KryptonForm
    {
        private List<EditorTrack> TrackSet = new List<EditorTrack>();
        private int currentIndex = 0;
        private bool first_load = false;
        private ToolTip tooltip = new ToolTip();
        public event EventHandler Saved;
        private string cover_filename;
        public TrackEditor(IList<TrackInfo> selection)
        {
            foreach (TrackInfo track in selection)
            {
                TrackSet.Add(new EditorTrack(track));
            }
            InitializeComponent();
        }
        void SetTip(Control ctrl,string tip)
        {
            tooltip.SetToolTip(ctrl, tip);
        }
        private void TrackEditor_Load(object sender, EventArgs e)
        {
            
            IconThemeUtils.SetWindowIcon(this, Properties.Resources.music_player_banshee_16);
            tooltip.AutoPopDelay = 5000;
            tooltip.InitialDelay = 500;
            tooltip.ReshowDelay = 10;
            SetTip(TrackNumberIterator, Catalog.GetString("Automatically set all track numbers in increasing order"));
            SetTip(TrackCountSync, Catalog.GetString("Set all track counts to this value"));
            SetTip(ArtistSync, Catalog.GetString("Set all artists to this value"));
            SetTip(AlbumSync, Catalog.GetString("Set all albums to this value"));
            SetTip(GenreSync, Catalog.GetString("Set all genres to this value"));
            SetTip(YearSync, Catalog.GetString("Set all years to this value"));
            SetTip(SyncAll, Catalog.GetString("Apply the values of this track set for the Artist, Album Title, Genre, Track count, Year, and Rating fields to the rest of the selected tracks in this editor."));
            SetTip(RatingSync, Catalog.GetString("Set all ratings to this value"));
            foreach (string genre in Globals.Library.GetGenreList())
            {
                if(!string.IsNullOrEmpty(genre))
                    Genre.Items.Add(genre);
            }
            Next.Visible = TrackSet.Count > 1;
            Previous.Visible = TrackSet.Count > 1;
            //tabControl1.TabPages.Remove(tabPage2);
            //Glade["MultiTrackButtons"].Visible = TrackSet.Count > 1;
            TrackNumberIterator.Visible = TrackSet.Count > 1;
            TrackCountSync.Visible = TrackSet.Count > 1;
            ArtistSync.Visible = TrackSet.Count > 1;
            AlbumSync.Visible = TrackSet.Count > 1;
            GenreSync.Visible = TrackSet.Count > 1;
            YearSync.Visible = TrackSet.Count > 1;
            RatingSync.Visible = TrackSet.Count > 1;
            EnterNext.Visible = TrackSet.Count > 1;
            SyncAll.Visible = TrackSet.Count > 1;
            LoadTrack(0);
        }
        private void LoadTrack(int index)
        {
            if (index < 0 || index >= TrackSet.Count)
            {
                return;
            }

            SetCoverImage(null);

            EditorTrack track = TrackSet[index] as EditorTrack;

            try
            {
                TrackNumber.Value = track.TrackNumber;
            }
            catch {
                TrackNumber.Value = 0;
            }
            TrackCount.Value = track.TrackCount;
            Year.Text = track.Year.ToString();
            //rating_entry.Value = (int)track.Rating;

            Artist.Text = track.Artist;
            Album.Text = track.Album;
            Title.Text = track.Title;
            Genre.Text = track.Genre;

            //(Glade["DurationLabel"] as Label).Text = String.Format("{0}:{1}",
            //    track.Track.Duration.Minutes, (track.Track.Duration.Seconds).ToString("00"));
           // (Glade["PlayCountLabel"] as Label).Text = track.Track.PlayCount.ToString();
           // (Glade["LastPlayedLabel"] as Label).Text = track.Track.LastPlayed == DateTime.MinValue ?
           //     Catalog.GetString("Never played") : track.Track.LastPlayed.ToString();
           // (Glade["ImportedLabel"] as Label).Text = track.Track.DateAdded == DateTime.MinValue ?
           //     Catalog.GetString("Unknown") : track.Track.DateAdded.ToString();

            if (first_load)
            {
               EmbedCoverArt.Checked = false;
               CopyCoverArt.Checked = true;
                first_load = false;
            }
            else
            {
                EmbedCoverArt.Checked = track.EmbedCoverArt;
                CopyCoverArt.Checked = track.CopyCoverArt;
            }

            this.Text = TrackSet.Count > 1
                ? String.Format("Editing song {0} of {1}", index + 1, TrackSet.Count)
                : String.Format("Editing {0}", track.Title);

            if (track.Uri.IsLocalPath)
            {
                Uri.Text = System.IO.Path.GetFileName(track.Uri.LocalPath);
                Location.Text = System.IO.Path.GetDirectoryName(track.Uri.LocalPath);
            }
            else
            {
                Uri.Text = track.Uri.ToString();
                Location.Text = String.Empty;
            }

            FileSize.Text = "Unknown";

            //Cornel -- Hopefully later today i should get cd audio running
            //if (!(track.Track is AudioCdTrackInfo) && !track.ProcessedStream)
            if (!track.ProcessedStream)
            {
                track.ProcessedStream = true;

                if (track.Uri.Scheme == System.Uri.UriSchemeFile)
                {
                    try
                    {
                        System.IO.FileInfo info = new System.IO.FileInfo(track.Uri.LocalPath);
                        track.FileSize = info.Length;
                    }
                    catch
                    {
                    }
                }

                try
                {
                    TagLib.File file = StreamTagger.ProcessUri(track.Uri);
                    //Cornel TODO -  Fix this
                   /* try {
                        TagLib.IPicture [] pictures = file.Tag.Pictures;
                        
                        if(pictures != null && pictures.Length > 0) {
                            TagLib.IPicture cover_picture = null;
                            foreach(TagLib.IPicture picture in pictures) {
                                if(cover_picture == null) {
                                    cover_picture = picture;
                                }
                                
                                if(picture.Type == TagLib.PictureType.FrontCover) {
                                    cover_picture = picture;
                                    break;
                                }
                            }
                            
                            if(cover_picture != null) {
                                Gdk.Pixbuf pixbuf = new Gdk.Pixbuf(cover_picture.Data.Data);
                                
                                track.CoverArtThumbnail = pixbuf.ScaleSimple(100, 100, Gdk.InterpType.Bilinear);
                            }
                        }
                    } catch {
                    }
                    */
                    try {
                        if (string.IsNullOrEmpty(track.CoverArtFilename))
                        {
                            Image img = Properties.Resources.image_missing;
                            SetCoverImage(img);
                        }
                        else
                        {
                            Image pixbuf = Image.FromFile(track.CoverArtFilename);
                            cover_filename = track.CoverArtFilename;
                            track.CoverArtThumbnail = pixbuf;
                            SetCoverImage(pixbuf);
                        }
                    }
                    catch {
                        
                    }
                    if (file.AudioProperties != null)
                    {
                        track.Bitrate = file.AudioProperties.Bitrate;
                        track.SampleRate = file.AudioProperties.SampleRate;
                        track.Channels = file.AudioProperties.Channels;
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
                catch (Exception)
                {
                    track.Bitrate = -1;
                }
            }

            if (track.ProcessedStream)
            {
                FileSize.Text = String.Format("{0:0.0} MB", (double)track.FileSize / 1024.0 / 1024.0);

                if (track.Bitrate > 0)
                {
                    BitRate.Text = String.Format("{0} kbps", track.Bitrate);
                    SampleRate.Text = String.Format("{0} Hz", track.SampleRate);
                    Channels.Text = String.Format("{0}", track.Channels);
                }
                else
                {
                    BitRate.Text = String.Format("{0} kbps", track.Bitrate);
                    SampleRate.Text = String.Format("{0} Hz", track.SampleRate);
                    Channels.Text = String.Format("{0}", track.Channels);
                }

                SetCoverImage(track.CoverArtThumbnail);
            }

            Previous.Enabled = index > 0;
            Next.Enabled = index < TrackSet.Count - 1;
            EnterNext.Enabled = Next.Enabled;
        }
        private void SetCoverImage(Image image)
        {
            CoverImage.Image = image;
        }
        private EditorTrack UpdateCurrent()
        {
            if (currentIndex < 0 || currentIndex >= TrackSet.Count)
            {
                return null;
            }

            EditorTrack track = TrackSet[currentIndex] as EditorTrack;

            track.TrackNumber = (uint)TrackNumber.Value;
            track.TrackCount = (uint)TrackNumber.Value;
            track.Artist = Artist.Text;
            track.Album = Album.Text;
            track.Title = Title.Text;
            track.Genre = Genre.Text;
            track.CopyCoverArt = CopyCoverArt.Checked;
            track.EmbedCoverArt = EmbedCoverArt.Checked;
            track.CoverArtFilename = cover_filename;
            //track.Rating = (uint)rating_entry.Value;

            try
            {
                track.Year = Convert.ToInt32(Year.Text);
            }
            catch
            {
                track.Year = 0;
            }

            return track;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            UpdateCurrent();

            foreach (EditorTrack track in TrackSet)
            {
                SaveTrack(track, true);
            }

            EventHandler handler = Saved;
            if (handler != null)
            {
                handler(this, new EventArgs());
            }
        }
        private void SaveTrack(EditorTrack track, bool writeToDatabase)
        {
            track.Save();

            if (writeToDatabase)
            {
                track.Track.Save();

                if (LibrarySchema.WriteMetadata.Get())
                {
                    SaveToFile(track);
                }
            }

            if (track.Track == PlayerEngineCore.CurrentTrack)
            {
                PlayerEngineCore.TrackInfoUpdated();
            }
            this.Close();
        }
        private void SaveToFile(EditorTrack track)
        {
            Banshee.Kernel.Scheduler.Schedule(new SaveTrackMetadataJob(track.Track),
            Banshee.Kernel.JobPriority.Highest);
        }

        private void Previous_Click(object sender, EventArgs e)
        {
            UpdateCurrent();
            LoadTrack(--currentIndex);
        }

        private void Next_Click(object sender, EventArgs e)
        {
            UpdateCurrent();
            LoadTrack(++currentIndex);
        }
        private string last_path = null;
        private void CoverImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog chooser = new OpenFileDialog();
            chooser.Filter = "Image(jpg)|*.jpg|Image(png)|*.png|Image(bmp)|*.bmp";
            try
            {
                string path = (TrackSet[currentIndex] as EditorTrack).CoverArtFilename;
                path = System.IO.Path.GetDirectoryName(path);
                if (path != null && path != String.Empty)
                {
                    chooser.InitialDirectory = path;
                }
                else if (last_path != null && last_path != String.Empty)
                {
                    path = System.IO.Path.GetDirectoryName(last_path);
                    chooser.InitialDirectory = path;
                }
            }
            catch
            {
            }
            DialogResult dr = chooser.ShowDialog(this);
            if (dr == DialogResult.OK)
            {
                last_path = chooser.FileName;
                Image img = Image.FromFile(chooser.FileName);
                (TrackSet[currentIndex] as EditorTrack).CoverArtFilename = chooser.FileName;
                (TrackSet[currentIndex] as EditorTrack).CoverArtThumbnail = img;
                SetCoverImage(img);
                cover_filename = chooser.FileName;
            }
        }

        private void EnterNext_Click(object sender, EventArgs e)
        {
            Next_Click(sender, e);
            Title.Enabled= true;
            Title.SelectAll();
        }

        private void GenreSync_Click(object sender, EventArgs e)
        {
            foreach (EditorTrack track in TrackSet)
            {
                track.Genre = Genre.Text;
            }
        }

        private void ArtistSync_Click(object sender, EventArgs e)
        {
            foreach (EditorTrack track in TrackSet)
            {
                track.Artist = Artist.Text;
            }
        }

        private void AlbumSync_Click(object sender, EventArgs e)
        {
            foreach (EditorTrack track in TrackSet)
            {
                track.Album = Album.Text;
            }
        }

        private void TrackCountSync_Click(object sender, EventArgs e)
        {
            foreach (EditorTrack track in TrackSet)
            {
                track.TrackCount = (uint)TrackCount.Value;
            }
        }

        private void YearSync_Click(object sender, EventArgs e)
        {
            foreach (EditorTrack track in TrackSet)
            {
                try
                {
                    track.Year = Convert.ToInt32(Year.Text);
                }
                catch
                {
                    track.Year = 0;
                }
            }
        }

        private void RatingSync_Click(object sender, EventArgs e)
        {
            /*foreach (EditorTrack track in TrackSet)
            {
                track.Rating = (uint)rating_entry.Value;
            }*/
        }

        private void TrackNumberIterator_Click(object sender, EventArgs e)
        {
            int i = 1;
            foreach (EditorTrack track in TrackSet)
            {
                track.TrackNumber = (uint)i++;
                track.TrackCount = (uint)TrackSet.Count;
            }

            EditorTrack current_track = TrackSet[currentIndex] as EditorTrack;
            TrackNumber.Value = (int)current_track.TrackNumber;
            TrackCount.Value = (int)current_track.TrackCount;
        }

        private void Cancelbutton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void SyncAll_Click(object sender, EventArgs e)
        {
            ArtistSync_Click(sender, e);
            AlbumSync_Click(sender, e);
            GenreSync_Click(sender, e);
            TrackCountSync_Click(sender, e);
            YearSync_Click(sender, e);
        }

        private void SyncCoverArt_Click(object sender, EventArgs e)
        {

        }
    }
    internal class EditorTrack
    {
        private TrackInfo track;

        public string Artist;
        public string Album;
        public string Title;
        public string Genre;
        public SafeUri Uri;

        public uint TrackNumber;
        public uint TrackCount;
        public int Year;
        public uint Rating;

        // temp properties
        public bool ProcessedStream = false;
        public string CoverArtFilename;
        public bool EmbedCoverArt;
        public bool CopyCoverArt;
        public Image CoverArtThumbnail;
        public int Channels;
        public int Bitrate;
        public int SampleRate;
        public long FileSize;

        public EditorTrack(TrackInfo track)
        {
            this.track = track;
            Revert();
        }

        public void Revert()
        {
            Artist = track.Artist == null ? String.Empty : track.Artist;
            Album = track.Album == null ? String.Empty : track.Album;
            Title = track.Title == null ? String.Empty : track.Title;
            Genre = track.Genre == null ? String.Empty : track.Genre;
            TrackNumber = track.TrackNumber;
            TrackCount = track.TrackCount;
            Year = track.Year;
            Uri = track.Uri;
            Rating = track.Rating;
            CoverArtFilename = track.CoverArtFileName;
        }

        public void Save()
        {
            track.Artist = Artist;
            track.Album = Album;
            track.Title = Title;
            track.Genre = Genre;
            track.TrackNumber = TrackNumber;
            track.TrackCount = TrackCount;
            track.Uri = Uri;
            track.Year = Year;
            track.Rating = Rating;
            track.CoverArtFileName = CoverArtFilename;
        }

        public TrackInfo Track
        {
            get { return track; }
        }
    }
}